#include "../common/config.h"
#include "fsorder.h"
#include <mysql_connection.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>

extern int gRunThread;
extern LoggerPtr gLogger;
void * APR_THREAD_FUNC fetch_order(apr_thread_t *thd, void *data)
{
retry:

    try
    {

        sql::Connection *con = GetDBC();
        sql::PreparedStatement *stmtup, *stmt;
        sql::ResultSet *res;

        if (con != NULL)
        {
            LOG4CXX_INFO(gLogger, "get database connect  success");
        }
        else
        {
            LOG4CXX_WARN(gLogger, "get database connect  failed");
        }

        stmt = con->prepareStatement("select id,acct,caller,called  from ordercall where ordercall.result = '0' and calltime<=now() order by id asc");
        stmtup = con -> prepareStatement ("update ordercall set result='process',calltime=now() where id>=(?) and id<=(?)");

        while (gRunThread)
        {
            //res = stmt->executeQuery("select id,acct,caller,called  from ordercall where ordercall.result = '0' and calltime<=now() order by id asc");
            res = stmt->executeQuery();
            string startid = "-1", endid = "-1";

            while (res->next())
            {
                ordercall_info_t* pNewJob = new ordercall_info_t();
                pNewJob->id = res->getString(1);
                pNewJob->acct = res->getString(2);
                pNewJob->caller = res->getString(3);
                pNewJob->called = res->getString(4);

                if (pNewJob->called.empty())
                {
                    pNewJob->called = "empty";
                }

                if (strcmp(startid.c_str(), "-1") == 0)
                {
                    startid = pNewJob->id;
                }

                endid = pNewJob->id;
                LOG4CXX_TRACE(gLogger, "get job id=" << pNewJob->id << "acct= " << pNewJob->acct << " caller=" << pNewJob->caller << " called=" << pNewJob->called);
                apr_queue_push(jobqueue, pNewJob);
            }

            delete res;

            if (strcmp(startid.c_str(), "-1") != 0)
            {
                stmtup -> setString (1, startid.c_str());
                stmtup -> setString (2, endid.c_str());
                stmtup -> executeUpdate();
            }

            apr_sleep(100000);
        }

        delete stmtup;
        delete stmt;
        ReleaseDBC(con);
    }
    catch (sql::SQLException &e)
    {
        LOG4CXX_WARN(gLogger, "err:" << e.what() << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState());
        goto retry;
    }

    return 0;
}

void * APR_THREAD_FUNC result_order(apr_thread_t *thd, void *data)
{
retry_result:

    try
    {

        sql::Connection *con = GetDBC();

        if (con != NULL)
        {
            LOG4CXX_INFO(gLogger, "get database connect  success");
        }
        else
        {
            LOG4CXX_WARN(gLogger, "get database connect  failed");
        }


        sql::Statement *stmt = con->createStatement();

        while (gRunThread)
        {
            ordercall_info_t* pJob = NULL;

            while (apr_queue_pop (resultqueue, (void**)&pJob) == APR_SUCCESS)
            {
                stmt->execute(("UPDATE ordercall SET calltime=now(),ordercall.result='" + pJob->result + "' where id=" + pJob->id).c_str());
                delete pJob;
                pJob = NULL;
            }
        }

        delete stmt;
        ReleaseDBC(con);
    }
    catch (sql::SQLException &e)
    {
        LOG4CXX_WARN(gLogger, "err:" << e.what() << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState());
        goto retry_result;
    }

    return 0;
}


void * APR_THREAD_FUNC fetch_auth(apr_thread_t *thd, void *data)
{
retry:

	try
	{
		sql::Connection *con = GetDBC();
		sql::PreparedStatement *stmtup, *stmt;
		sql::ResultSet *res;

		if (con != NULL)
		{
			LOG4CXX_INFO(gLogger, "get database connect  success");
		}
		else
		{
			LOG4CXX_WARN(gLogger, "get database connect  failed");
		}

		stmt = con->prepareStatement("select id,acct,caller,authcode  from orderauth where ( orderauth.result is NULL )  and calltime<=now() order by id asc");
		stmtup = con -> prepareStatement ("update orderauth set result='process',calltime=now() where id>=(?) and id<=(?)");

		while (gRunThread)
		{
			
			res = stmt->executeQuery();
			string startid = "-1", endid = "-1";

			while (res->next())
			{
				orderAuth_info_t* pNewJob = new orderAuth_info_t();
				pNewJob->id = res->getString(1);
				pNewJob->acct = res->getString(2);
				pNewJob->caller = res->getString(3);
				pNewJob->authcode = res->getString(4);

				if (strcmp(startid.c_str(), "-1") == 0)
				{
					startid = pNewJob->id;
				}
				endid = pNewJob->id;
				LOG4CXX_INFO(gLogger, "get auth job id=" << pNewJob->id << "acct= " << pNewJob->acct << " caller=" << pNewJob->caller << " authcode=" << pNewJob->authcode);
				apr_queue_push(authqueue, pNewJob);
			}

			delete res;

			if (strcmp(startid.c_str(), "-1") != 0)
			{
				stmtup -> setString (1, startid.c_str());
				stmtup -> setString (2, endid.c_str());
				stmtup -> executeUpdate();
			}

			apr_sleep(100000);
		}

		delete stmtup;
		delete stmt;
		ReleaseDBC(con);
	}
	catch (sql::SQLException &e)
	{
		LOG4CXX_WARN(gLogger, "err:" << e.what() << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState());
		goto retry;
	}

	return 0;
}

void * APR_THREAD_FUNC result_auth(apr_thread_t *thd, void *data)
{
retry_result:

	try
	{

		sql::Connection *con = GetDBC();

		if (con != NULL)
		{
			LOG4CXX_INFO(gLogger, "get database connect  success");
		}
		else
		{
			LOG4CXX_WARN(gLogger, "get database connect  failed");
		}


		sql::Statement *stmt = con->createStatement();

		while (gRunThread)
		{
			orderAuth_info_t* pJob = NULL;

			while (apr_queue_pop (authresultqueue, (void**)&pJob) == APR_SUCCESS)
			{
				stmt->execute(("UPDATE orderauth SET calltime=now(),orderauth.result='" + pJob->result + "' where id=" + pJob->id).c_str());
				delete pJob;
				pJob = NULL;
			}
		}

		delete stmt;
		ReleaseDBC(con);
	}
	catch (sql::SQLException &e)
	{
		LOG4CXX_WARN(gLogger, "err:" << e.what() << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState());
		goto retry_result;
	}

	return 0;
}
